package com.gbb.simple.utils;

import android.text.TextUtils;
import android.util.Log;

import com.gbb.resource.R;
import com.gbb.simple.bean.response.DefaultResult;
import com.gbb.common.utils.ToastUtil;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class JsonUtils {

    private static final String TAG = JsonUtils.class.getSimpleName();

    public static <T extends Object> DefaultResult<T> fromJson(String json,Class<T> childClazz,Type type){
        if(TextUtils.isEmpty(json) || type == null) {
            return null;
        }
        DefaultResult<T> object = null;
        try {
            Gson gson = new Gson();
            object = gson.fromJson(json,type);
        } catch(JsonSyntaxException e) {
            ToastUtil.showToast(R.string.response_error_data);
            Log.e(TAG,"not json data:" + json,e);
        }
        return object;
    }

    public static <T extends Object> T fromJson(String json,Class<T> clazz){
        if(TextUtils.isEmpty(json)) {
            return null;
        }
        T object = null;
        try {
            Gson gson = new Gson();
            object = gson.fromJson(json,clazz);
        } catch(JsonSyntaxException e) {
            ToastUtil.showToast(R.string.response_error_data);
            Log.e(TAG,"not json data:" + json,e);
        }
        return object;
    }

    public static <T extends Object> List<T> fromArrayJson(String json,Class<T> clazz){
        if(TextUtils.isEmpty(json)) {
            return null;
        }
        List<T> objects = new ArrayList<>();
        T object = null;
        try {
            Gson gson = new Gson();

            JsonParser parser = new JsonParser();
            JsonArray jsonArray = parser.parse(json).getAsJsonArray();
            for(JsonElement jsonElement : jsonArray) {
                object = gson.fromJson(jsonElement,clazz);
                objects.add(object);
            }

        } catch(JsonSyntaxException e) {
            ToastUtil.showToast(R.string.response_error_data);
            Log.e(TAG,"not json data:" + json,e);
        }
        return objects;
    }

    public static String toJson(Object src){
        Gson gson = new Gson();
        return src == null ? null : gson.toJson(src);
    }

    /**
     * List<Map<String,Object>> 转 List<Bean>
     *
     * @param mapList
     * @param beanClass
     * @return
     */
    public static <E> List<E> mapListToBeanList(List<Map<String, Object>> mapList,Class<E> beanClass){
        List<E> resultList = new ArrayList<>();
        try {
            for(Map<String, Object> map : mapList) {
                resultList.add(map2Bean(beanClass.newInstance(),map));
            }
        } catch(Exception e) {
            throw new RuntimeException("transMapList2BeanList Error " + e);
        }
        return resultList;
    }

    /**
     * Map 转 Bean <br/>
     * 1.只支持基本数据类型及扩展 <br/>
     * 2.只支持以及转换
     *
     * @param t
     * @param map
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static <T> T map2Bean(T t,Map<String, Object> map) throws Exception{
        Class<?> clazz = t.getClass();
        // 实例化类
        T entity = (T) clazz.newInstance();
        Set<String> keys = map.keySet();
        // 变量map 赋值
        for(String key : keys) {
            String fieldName = key;
            // 判断是sql 还是hql返回的结果
            if(key.equals(key.toUpperCase())) {
                // 获取所有域变量
                Field[] fields = clazz.getDeclaredFields();
                for(Field field : fields) {
                    if(field.getName().toUpperCase().equals(key)) {
                        fieldName = field.getName();
                    }
                    break;
                }
            }
            // 设置赋值
            try {
                // 参数的类型 clazz.getField(fieldName)
                Class<?> paramClass = clazz.getDeclaredField(fieldName).getType();
                // 拼装set方法名称
                String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
                // 根据名称获取方法
                Method method = clazz.getMethod(methodName,paramClass);
                // 调用invoke执行赋值
                method.invoke(entity,map.get(key));
            } catch(Exception e) {
                // NoSuchMethod
            }
        }

        return entity;
    }

}
